#!/usr/bin/sh

UNITFILE="/etc/nmtrust/trusted_units"

###############################################################################

usage() {
    echo "Usage: ttrust [OPTION...]
Toggle the activation of certain systemd units based on the trust of the current network connections.

Options:
    -f      specify an alternative location for the trusted unit file
    -s      display the status of the trusted units and exit
    -x      stop all trusted units, regardless of network trust
    -t      start all trusted units, regardless of network trust
    -q      be quiet"
}

file_check() {
    if [ ! -f "$UNITFILE" ]; then
        if [ "$quiet" != true ]; then
            echo "Could not locate trusted unit file: $UNITFILE"
        fi
        exit 1
    fi
}

find_nmtrust() {
    if hash nmtrust 2> /dev/null; then
        NMTRUST=nmtrust
    else
        echo "Could not find nmtrust"
        exit 127
    fi
}

extract_user() {
    echo "$1" | sed 's/.*user:\([^,]*\).*/\1/'
}

get_trusted_units() {
    TRUSTED_SYSTEM_UNITS=$(grep -v '^#\|,.*user:' "$UNITFILE" | cut -d ',' -f1)
    OFFLINE_SYSTEM_UNITS=$(grep -v '^#\|,.*user:' "$UNITFILE" | grep ',.*allow_offline' | cut -d ',' -f1)
    TRUSTED_USER_UNITS=$(grep -v '^#' "$UNITFILE" | grep ',.*user:')
    OFFLINE_USER_UNITS=$(grep -v '^#' "$UNITFILE" | grep ',.*user:'  | grep ',.*allow_offline')
}

user_toggle() {
    unit_user=$(extract_user "$line")
    unit=$(echo "$line" | cut -d ',' -f1)
    if [ "$1" = "status" ]; then
        command="SYSTEMD_COLORS=1 systemctl $1 --user $unit | sed '1p;/^\s*Active:/!d'"
    else
        command="systemctl $1 --user $unit"
    fi
    if [ "$unit_user" = "$USER" ]; then
        eval "$command"
    else
        sudo -u "$unit_user" bash -c "export XDG_RUNTIME_DIR=/run/user/$(id -u "$unit_user"); $command"
    fi
}

start() {
    if [ -n "$TRUSTED_SYSTEM_UNITS" ]; then
        if [ "$quiet" != true ]; then
            echo "Starting trusted system units"
        fi
        systemctl start $TRUSTED_SYSTEM_UNITS
    fi
    if [ -n "$TRUSTED_USER_UNITS" ]; then
        if [ "$quiet" != true ]; then
            echo "Starting trusted user units"
        fi
        echo "$TRUSTED_USER_UNITS" | while read -r line; do
            user_toggle "start" "$line"
        done
    fi
}

stop() {
    if [ -n "$TRUSTED_SYSTEM_UNITS" ]; then
        if [ "$quiet" != true ]; then
            echo "Stopping trusted system units"
        fi
        systemctl stop $TRUSTED_SYSTEM_UNITS
    fi
    if [ -n "$TRUSTED_USER_UNITS" ]; then
        if [ "$quiet" != true ]; then
            echo "Stopping trusted user units"
        fi
        echo "$TRUSTED_USER_UNITS" | while read -r line; do
            user_toggle "stop" "$line"
        done
    fi
}

start_offline() {
    stop
    if [ -n "$OFFLINE_SYSTEM_UNITS" ]; then
        if [ "$quiet" != true ]; then
            echo "Starting trusted system offline units"
        fi
        systemctl start "$OFFLINE_SYSTEM_UNITS"
    fi
    if [ -n "$OFFLINE_USER_UNITS" ]; then
        if [ "$quiet" != true ]; then
            echo "Starting trusted user offline units"
        fi
        echo "$OFFLINE_USER_UNITS" | while read -r line; do
            user_toggle "start" "$line"
        done
    fi
}

status() {
    echo "Systemd system units:"
    for unit in $TRUSTED_SYSTEM_UNITS
    do
        SYSTEMD_COLORS=1 systemctl status "$unit" | sed '1p;/^\s*Active:/!d'
    done
    echo "Systemd user units:"
    echo "$TRUSTED_USER_UNITS" | while read -r line; do
        user_toggle "status" "$line"
    done
}

while getopts ":f:sxtqh" opt; do
    case $opt in
        f)
            UNITFILE=$OPTARG
            ;;
        q)
            quiet=true
            ;;
        s)
            status=true
            ;;
        x)
            stopall=true
            ;;
        t)
            startall=true
            ;;
        :)
            echo "Option -$OPTARG requires an argument."
            usage
            exit 1
            ;;
        h | *)
            usage
            exit
            ;;
    esac
done

# Check if the trusted unit file exists.
file_check

# Get the trusted units
get_trusted_units

# If the status was requested, display it.
if [ "$status" = true ]; then
    status
    exit $?
fi

# If stopping everything was requested, do it.
if [ "$stopall" = true ]; then
    stop
    exit $?
fi

# If starting everything was requested, do it.
if [ "$startall" = true ]; then
    start
    exit $?
fi

# Execute nmtrust.
find_nmtrust
$NMTRUST
result=$?

# Toggle the units as appropriate.
if [ $result -eq 0 ]; then
    start
    exit $?
elif [ $result -eq 4 ]; then
    start_offline
    exit $?
else
    stop
    exit $?
fi
